import pandas as pd
import numpy as np
from datetime import datetime
import sqlite3
import json
from typing import Dict, List, Optional, Tuple
import streamlit as st
from matplotlib import pyplot as plt


class WeaponStatistics:
    def __init__(self, db_path: str = "weapon_stats.db"):

        self.db_path = db_path
        self.initialize_database()

        #Apex Legends常见枪械
        self.weapon_types = {
            '突击步枪': ['R-301', 'Hemlok', 'Flatline', 'Havoc'],
            '冲锋枪': ['R-99', 'CAR', 'Volt', 'Prowler'],
            '霰弹枪': ['Peacekeeper', 'Mastiff', 'EVA-8', 'Mozambique'],
            '狙击枪': ['Kraber', 'Longbow', 'Sentinel', 'Charge Rifle'],
            '手枪': ['Wingman', 'RE-45', 'P2020'],
            '轻机枪': ['Spitfire', 'Devotion', 'L-STAR', 'Rampage']
        }

        self.all_weapons = []
        for weapon_list in self.weapon_types.values():
            self.all_weapons.extend(weapon_list)

    def initialize_database(self):

        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()


        cursor.execute('''
        CREATE TABLE IF NOT EXISTS weapon_records (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            weapon_name TEXT NOT NULL,
            game_date DATE NOT NULL,
            games_used INTEGER DEFAULT 0,
            total_kills INTEGER DEFAULT 0,
            headshot_kills INTEGER DEFAULT 0,
            total_damage INTEGER DEFAULT 0
        )
        ''')

        conn.commit()
        conn.close()

    def add_weapon_record(self, weapon_name: str, game_date: str,
                          games_used: int = 1, kills: int = 0,
                          headshots: int = 0, damage: int = 0):

        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()

        # 插入记录
        cursor.execute('''
        INSERT INTO weapon_records 
        (weapon_name, game_date, games_used, total_kills, headshot_kills, total_damage)
        VALUES (?, ?, ?, ?, ?, ?)
        ''', (weapon_name, game_date, games_used, kills, headshots, damage))

        conn.commit()
        conn.close()

    def get_total_games(self) -> int:

        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()

        cursor.execute('SELECT SUM(games_used) FROM weapon_records')
        result = cursor.fetchone()
        total_games = result[0] if result[0] else 0

        conn.close()
        return total_games

    def get_weapon_stats(self, weapon_name: Optional[str] = None) -> pd.DataFrame:

        conn = sqlite3.connect(self.db_path)

        if weapon_name:
            query = '''
            SELECT 
                weapon_name,
                (SUM(games_used) * 100.0 / (SELECT SUM(games_used) FROM weapon_records)) as usage_rate,
                SUM(games_used) as total_games,
                (SUM(headshot_kills) * 100.0 / NULLIF(SUM(total_kills), 0)) as headshot_rate,
                SUM(total_kills) * 1.0 / NULLIF(SUM(games_used), 0) as kills_per_game,
                SUM(total_damage) * 1.0 / NULLIF(SUM(games_used), 0) as damage_per_game
            FROM weapon_records 
            WHERE weapon_name = ?
            GROUP BY weapon_name
            '''
            df = pd.read_sql_query(query, conn, params=(weapon_name,))
        else:
            query = '''
            SELECT 
                weapon_name,
                (SUM(games_used) * 100.0 / (SELECT SUM(games_used) FROM weapon_records)) as usage_rate,
                SUM(games_used) as total_games,
                (SUM(headshot_kills) * 100.0 / NULLIF(SUM(total_kills), 0)) as headshot_rate,
                SUM(total_kills) * 1.0 / NULLIF(SUM(games_used), 0) as kills_per_game,
                SUM(total_damage) * 1.0 / NULLIF(SUM(games_used), 0) as damage_per_game
            FROM weapon_records 
            GROUP BY weapon_name
            ORDER BY usage_rate DESC
            '''
            df = pd.read_sql_query(query, conn)

        conn.close()
        return df

    def get_top_weapons(self, limit: int = 10, by: str = 'usage_rate') -> pd.DataFrame:

        valid_sort_columns = ['usage_rate', 'headshot_rate', 'kills_per_game', 'damage_per_game']
        if by not in valid_sort_columns:
            by = 'usage_rate'

        query = f'''
        SELECT 
            weapon_name,
            (SUM(games_used) * 100.0 / (SELECT SUM(games_used) FROM weapon_records)) as usage_rate,
            SUM(games_used) as total_games,
            (SUM(headshot_kills) * 100.0 / NULLIF(SUM(total_kills), 0)) as headshot_rate,
            SUM(total_kills) * 1.0 / NULLIF(SUM(games_used), 0) as kills_per_game,
            SUM(total_damage) * 1.0 / NULLIF(SUM(games_used), 0) as damage_per_game
        FROM weapon_records 
        GROUP BY weapon_name
        ORDER BY {by} DESC
        LIMIT ?
        '''

        conn = sqlite3.connect(self.db_path)
        df = pd.read_sql_query(query, conn, params=(limit,))
        conn.close()

        return df

    def get_weapon_history(self, weapon_name: str, days: int = 30) -> pd.DataFrame:

        conn = sqlite3.connect(self.db_path)
        query = '''
        SELECT game_date, games_used, total_kills, headshot_kills, total_damage
        FROM weapon_records 
        WHERE weapon_name = ? AND date(game_date) >= date('now', ?)
        ORDER BY game_date DESC
        '''
        df = pd.read_sql_query(query, conn, params=(weapon_name, f'-{days} days'))
        conn.close()

        return df

    def add_batch_records(self, records: List[Dict]):

        for record in records:
            self.add_weapon_record(
                weapon_name=record.get('weapon_name'),
                game_date=record.get('game_date', datetime.now().strftime('%Y-%m-%d')),
                games_used=record.get('games_used', 1),
                kills=record.get('kills', 0),
                headshots=record.get('headshots', 0),
                damage=record.get('damage', 0)
            )

    def generate_sample_data(self, total_games: int = 1000):

        import random
        from datetime import datetime, timedelta

        # 清空现有数据
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute('DELETE FROM weapon_records')
        conn.commit()
        conn.close()

        # 生成30天的数据
        dates = [(datetime.now() - timedelta(days=i)).strftime('%Y-%m-%d')
                 for i in range(30)]

        records = []
        for date in dates:
            # 每天随机生成10-30场比赛
            daily_games = random.randint(10, 30)
            weapons_used = random.sample(self.all_weapons, random.randint(5, 10))

            for weapon in weapons_used:
                games_used = random.randint(1, min(5, daily_games))
                kills = random.randint(0, games_used * 3)
                headshots = random.randint(0, kills)
                damage = random.randint(kills * 100, kills * 200)

                records.append({
                    'weapon_name': weapon,
                    'game_date': date,
                    'games_used': games_used,
                    'kills': kills,
                    'headshots': headshots,
                    'damage': damage
                })

        self.add_batch_records(records)

    def export_to_csv(self, filename: str = "weapon_stats_export.csv"):
        df = self.get_weapon_stats()
        df.to_csv(filename, index=False, encoding='utf-8-sig')
        return filename


# Streamlit界面函数
def show_weapon_statistics():

    st.title(" Apex Legends 枪械使用统计")

    # 初始化统计对象
    weapon_stats = WeaponStatistics()

    # 侧边栏控制
    st.sidebar.header("数据管理")
    if st.sidebar.button("生成示例数据"):
        weapon_stats.generate_sample_data()
        st.sidebar.success("示例数据生成完成！")

    if st.sidebar.button("导出数据到CSV"):
        filename = weapon_stats.export_to_csv()
        st.sidebar.success(f"数据已导出到 {filename}")

    # 主界面
    tab1, tab2, tab3 = st.tabs(["总体统计", "枪械详情", "添加记录"])

    with tab1:
        st.header("枪械使用总体统计")

        # 选择排序方式
        sort_by = st.selectbox(
            "排序方式",
            ["使用率", "爆头率", "场均击杀", "场均伤害"],
            key="sort_by"
        )

        sort_mapping = {
            "使用率": "usage_rate",
            "爆头率": "headshot_rate",
            "场均击杀": "kills_per_game",
            "场均伤害": "damage_per_game"
        }


        df = weapon_stats.get_top_weapons(by=sort_mapping[sort_by])

        if not df.empty:
            # 格式化显示
            display_df = df[['weapon_name', 'usage_rate', 'total_games',
                             'headshot_rate', 'kills_per_game', 'damage_per_game']].copy()
            display_df.columns = ['枪械名称', '使用率(%)', '使用场数', '爆头率(%)', '场均击杀', '场均伤害']

            # 格式化数值
            display_df['使用率(%)'] = display_df['使用率(%)'].round(2)
            display_df['爆头率(%)'] = display_df['爆头率(%)'].round(2)
            display_df['场均击杀'] = display_df['场均击杀'].round(2)
            display_df['场均伤害'] = display_df['场均伤害'].round(1)

            st.dataframe(display_df, use_container_width=True)

            # 显示统计图表
            col1, col2 = st.columns(2)

            with col1:
                st.subheader("使用率TOP5")
                top_usage = df.nlargest(5, 'usage_rate')
                fig1, ax1 = plt.subplots()
                ax1.barh(top_usage['weapon_name'], top_usage['usage_rate'])
                ax1.set_xlabel('使用率(%)')
                st.pyplot(fig1)

            with col2:
                st.subheader("爆头率TOP5")
                top_hs = df.nlargest(5, 'headshot_rate')
                fig2, ax2 = plt.subplots()
                ax2.barh(top_hs['weapon_name'], top_hs['headshot_rate'])
                ax2.set_xlabel('爆头率(%)')
                st.pyplot(fig2)

        else:
            st.info("暂无数据，请先添加记录或生成示例数据")

    with tab2:
        st.header("枪械详细数据")

        selected_weapon = st.selectbox(
            "选择枪械",
            weapon_stats.all_weapons,
            key="weapon_detail"
        )

        if selected_weapon:
            stats = weapon_stats.get_weapon_stats(selected_weapon)
            history = weapon_stats.get_weapon_history(selected_weapon)

            if not stats.empty:
                st.metric("使用率", f"{stats.iloc[0]['usage_rate']:.2f}%")
                st.metric("使用场数", int(stats.iloc[0]['total_games']))
                st.metric("爆头率", f"{stats.iloc[0]['headshot_rate']:.2f}%")
                st.metric("场均击杀", f"{stats.iloc[0]['kills_per_game']:.2f}")
                st.metric("场均伤害", f"{stats.iloc[0]['damage_per_game']:.0f}")

                if not history.empty:
                    st.subheader("近期使用历史")
                    st.dataframe(history)

    with tab3:
        st.header("添加枪械使用记录")

        with st.form("add_weapon_record"):
            col1, col2 = st.columns(2)

            with col1:
                weapon_name = st.selectbox("枪械名称", weapon_stats.all_weapons)
                game_date = st.date_input("比赛日期", datetime.now())
                games_used = st.number_input("使用场数", min_value=1, value=1)

            with col2:
                kills = st.number_input("击杀数", min_value=0, value=0)
                headshots = st.number_input("爆头击杀数", min_value=0, value=0)
                damage = st.number_input("总伤害", min_value=0, value=0)

            if st.form_submit_button("添加记录"):
                weapon_stats.add_weapon_record(
                    weapon_name=weapon_name,
                    game_date=game_date.strftime('%Y-%m-%d'),
                    games_used=games_used,
                    kills=kills,
                    headshots=headshots,
                    damage=damage
                )
                st.success("记录添加成功！")


# 使用示例
if __name__ == "__main__":
    # 创建实例
    stats = WeaponStatistics()

    # 添加示例记录
    sample_data = [
        {
            'weapon_name': 'R-301',
            'game_date': '2024-01-15',
            'games_used': 5,
            'kills': 12,
            'headshots': 4,
            'damage': 2450
        },
        {
            'weapon_name': 'Wingman',
            'game_date': '2024-01-15',
            'games_used': 3,
            'kills': 8,
            'headshots': 3,
            'damage': 1800
        }
    ]

    stats.add_batch_records(sample_data)

    # 获取统计数据
    df = stats.get_weapon_stats()
    print("枪械统计数据:")
    print(df.to_string())